﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FDSimpleModelGenerator.Common;

/// <summary>
/// 数据类型格式器
/// </summary>
public class DbDataTypeFormatter
{
    private static readonly uint MaxIndexLenght = 64;

    /// <summary>
    /// 格式化数据类型
    /// </summary>
    /// <param name="dataType">数据类型</param>
    /// <param name="length">长度</param>
    /// <param name="precision">精度</param>
    /// <param name="isUnsigned">无符号</param>
    /// <returns></returns>
    public static string DataType(string dataType, int length = 0, int precision = 0, bool isUnsigned = false)
    {
        var dt = dataType.ToUpper().Trim();
        switch (dt)
        {
            case "VARCHAR":
            case "NVARCHAR":
            case "CHAR":
            case "NCHAR":
                return $" {dt}({length})";
            case "DECIMAL":
            //return $" {dt}({length}, {precision}){(isUnsigned ? " UNSIGNED" : "")}";
            case "BIGINT":
            case "INT":
            case "INTEGER":
            case "MEDIUMINT":
            case "TINYINT":
            case "SMALLINT":
            case "DOUBLE":
            case "FLOAT":
            case "NUMERIC":
            case "REAL":
                return $" {dt}{DataTypePrecision(length, precision)}{(isUnsigned ? " UNSIGNED" : "")}";
            default:
                return $" {dt}";
        }
    }

    private static string DataTypePrecision(int length, int precision)
    {
        if (length == 0 && precision == 0)
        {
            return string.Empty;
        }

        if (precision == 0)
        {
            return $"({length})";
        }

        return $"({length}, {precision})";
    }

    /// <summary>
    /// 一般性数据自定义格式
    /// </summary>
    /// <param name="value">数据值</param>
    /// <param name="formatter">数据格式化器</param>
    /// <param name="isValid">是否有效（默认判断是否为空）</param>
    /// <param name="defaultValue">默认值 </param>
    /// <returns></returns>
    public static string Format(string value, Func<string, string> formatter, Predicate<string> isValid = null,
        Func<string> defaultValue = null)
    {
        if (isValid != null)
        {
            return isValid(value) ? formatter(value) : defaultValue?.Invoke() ?? string.Empty;
        }

        if (value.IsNullOrEmpty())
        {
            return defaultValue?.Invoke() ?? string.Empty;
        }

        return formatter(value);
    }

    /// <summary>
    /// 可空
    /// </summary>
    /// <param name="isAllowNull">是否允许为空</param>
    /// <returns></returns>
    public static string AllowNull(bool isAllowNull)
    {
        return isAllowNull ? "" : " NOT NULL";
    }

    /// <summary>
    /// 主键
    /// </summary>
    /// <param name="keys">主键列</param>
    /// <returns></returns>
    public static string PrimaryKey(IEnumerable<string> keys)
    {
        return keys?.Count() == 0 ? "" : $"PRIMARY KEY({string.Join(",", keys)})";
    }

    /// <summary>
    /// 默认值 
    /// </summary>
    /// <param name="defaultValue">默认值 </param>
    /// <param name="dataType">数据类型</param>
    /// <returns></returns>
    public static string DefaultValue(string defaultValue, string dataType)
    {
        dataType = dataType.Trim().ToUpper();
        if (dataType.Contains("TEXT"))
        {
            return string.Empty;
        }

        var isNull = "NULL" == defaultValue?.Trim().ToUpper();
        var items = new[]
        {
            "TINYINT", "INT", "FLOAT", "DECIMAL", "DOUBLE", "BIT", "SHORT", "BIGINT", "INTEGER", "SMALLINT",
            "MEDIUMINT", "NUMERIC", "REAL", "TIMESTAMP"
        };
        var strDefault = defaultValue.Replace("'", "");
        defaultValue = isNull ? defaultValue :
            items.Contains(dataType) ? defaultValue :
            defaultValue.IndexOf('(') != -1 ? strDefault : $"'{strDefault}'";
        return defaultValue.IsNullOrEmpty() ? "" : $" DEFAULT {defaultValue}";
    }

    /// <summary>
    /// 索引名称
    /// </summary>
    /// <param name="namePrefix"></param>
    /// <param name="columns"></param>
    /// <returns></returns>
    public static string IndexName(string namePrefix, IEnumerable<string> columns)
    {
        var indexName = $"IDX_{namePrefix}_{string.Join("_", columns)}";
        if (indexName.Length <= MaxIndexLenght)
        {
            return indexName;
        }

        indexName = $"IDX_{namePrefix}_{string.Join("", columns)}";
        if (indexName.Length <= MaxIndexLenght)
        {
            return indexName;
        }

        indexName = $"{indexName[..32]}{Guid.NewGuid().ToString().Replace("-", "")[..24]}";

        return indexName;
    }

    /// <summary>
    /// 索引项
    /// </summary>
    /// <param name="namePrefix"></param>
    /// <param name="columns"></param>
    /// <returns></returns>
    public static string IndexColumns(IEnumerable<string> columns)
    {
        return $"({string.Join(",", columns)})";
    }

    /// <summary>
    /// 附加主键至结果
    /// </summary>
    /// <param name="sb">结果缓存</param>
    /// <param name="primaryKeys">主键列</param>
    /// <param name="isEmpty2Delete">是否主键列为空时，删除结尾分隔符",\r\n"</param>
    public static void CheckAddPrimaryKey(StringBuilder sb, IEnumerable<string> primaryKeys, bool isEmpty2Delete)
    {
        var keyString = PrimaryKey(primaryKeys);
        if (keyString.IsNullOrEmpty())
        {
            if (!isEmpty2Delete)
            {
                return;
            }

            if (sb[^1] != '\n') // 最后为\n
            {
                return;
            }

            while (sb[^1] != ',')
            {
                sb.Length--;
            }

            sb.Length--;
            sb.Append("\r\n");
            //if (sb.Length > 3)
            //{
            //    sb.Remove(sb.Length - 3, 3).Append("\r\n");
            //}
        }
        else
        {
            sb.Append($"{keyString}\r\n");
        }
    }
}